package main

import (
	"context"
	"fmt"
	"time"
)

type Tracker2 struct {
	ch   chan string   //日志上报
	stop chan struct{} //终止信号
}

func NewTracker() *Tracker2 {
	return &Tracker2{
		ch: make(chan string, 10),
	}
}

func (t *Tracker2) Event(ctx context.Context, data string) error {
	select {
	case t.ch <- data:
		fmt.Println("写入日志")
		return nil
	case <-ctx.Done():
		fmt.Println("上下文错误")
		return ctx.Err()
	}
}

func (t *Tracker2) Run() {
	for data := range t.ch {
		time.Sleep(1 * time.Second)
		fmt.Printf("data : %s\n", data)
	}
	fmt.Println("stop 信号写入")
	t.stop <- struct{}{}
}

func (t *Tracker2) Shutdown(ctx context.Context) {
	close(t.ch) //关闭日志通道，写入者就写不进去了
	fmt.Println("关闭日志通道")
	select {
	case <-t.stop: //日式上报关闭的信号量
		fmt.Println("stop 信号处理")
	case <-ctx.Done(): //stop时间很长的话，外部调用的超时控制
		fmt.Println("ctx 超时关闭")
	}
}

func main() {
	tr := NewTracker()
	go tr.Run() //交给调用者，是否启动协程
	_ = tr.Event(context.Background(), "test1")
	_ = tr.Event(context.Background(), "test2")
	_ = tr.Event(context.Background(), "test2")
	time.Sleep(3 * time.Second)
	ctx, cancel := context.WithDeadline(context.Background(), time.Now().Add(5*time.Second))
	defer cancel()
	tr.Shutdown(ctx)
}
